(ns ura.User
  (:require
   [reagent.core :as r]
   [reagent.dom :as rd]
   ;; [stylefy.core :as sty]
   [stylefy.reagent :as stylefy-reagent]
   [ajax.core :refer [GET POST PUT DELETE]]
   [ura.common :as uc :refer [log spy]]
   [ura.config :refer [getUrl]]
   [ura.ui :as ui]
   [ura.notify :refer [showNotify]]
   [ura.style :refer [attr]]
   [ura.table :refer [MyTable]]

   ["antd" :as ant]
   [re-com.core :as rc :refer [at]]
   
   [cljsjs.moment]
   [cljsjs.moment.locale.es]
   [cljsjs.moment.locale.de]
   [cljsjs.moment.locale.ja]
   [cljsjs.moment.locale.ru]
   [cljsjs.moment.locale.zh-cn]
   )
  )

(def tableData (r/atom {:data []
                        :page {:current 1 :page-size 15 :total 0}
                        }))
(def modal1 (r/atom false))
(def dataItem (r/atom {:roleIds #{} :orgIds #{128}}))


(def roleList (r/atom []))
(defn loadRoleList []
  (GET (getUrl "/ura/role")
       {
        :response-format :json
        :keywords? true
        :handler
        (fn [resp]
          (log "get role lsit" resp)
          (reset! roleList resp)
          )}
       )
  )

(def orgList (r/atom []))

(defn genOrgPath [org path]
  (let [label (:name org)
        parentId (:parent_id org)
        parentOrg (some #(when (= parentId (:id %)) %) @orgList)
        newPath (conj path label)
        ]
    (log "gen org path: " org parentOrg newPath)
    (if (nil? parentOrg)
      newPath
      (genOrgPath parentOrg newPath)
      )
    )
  )


(defn loadOrgList []
  (GET (getUrl "/ura/org")
       {
        :response-format :json
        :keywords? true
        :handler
        (fn [resp]
          (reset! orgList resp) ;; store all org data to orgList for genOrgPath use
          (reset! orgList (mapv (fn [o] (assoc o :group (genOrgPath o '()))) resp))
          (log "get org lsit" @orgList)
          )
        }
       )
  )

(defn loadData [& param]
  (log "query user data " [param (:page @tableData)])
  (GET (getUrl "/ura/user/page")
       {:params (merge (js->clj param) (:page @tableData))
        :response-format :json
        :keywords? true
        :handler
        (fn [resp]
          (log "get user data0 " resp)
          (reset! tableData resp)
          )
        })
  )


(defn saveItem [data]
  (let [ method (if (nil? data.id) POST PUT) ]
    (log "save user data A1 " data)
    (method (getUrl "/ura/user")
            {
             :headers {:content-type "application/json"}
             :body (js/JSON.stringify (clj->js data))
             :handler (fn [resp]
                        (log " userInfo " resp)
                        )
             :error-handler (fn [resp]
                              (log "error " resp)
                              ;; TODO show erro message
                              )
             :finally (fn []
                        (reset! modal1 false)
                        (loadData)
                        )
             })
    )
  )

(defn callDelete [data]
  (let [url (getUrl (str "/ura/user/" (:id data)))]
    (log "delete data: " data url)
    (DELETE url
            { :handler (fn [resp]
                         (loadData)
                         (log "delete data" resp)
                         )})))



(defn handleEdit [row]
  (log "get dataitem " row)
  (reset! dataItem row)
  (swap! dataItem assoc :roleIds (set (:roleIds @dataItem)))
  (swap! dataItem assoc :orgIds  (set (:orgIds @dataItem)))
  (reset! modal1 true)
  )


(defn pwdform []
  (let [isShowPwd (r/atom true)
        passwordAtom (r/cursor dataItem [:password])
        ]
    (fn []
      [:div (attr :flex)
       [:input {:class "form-control rc-input-text-field"
                :type (if @isShowPwd :password :text)
                :placeholder "请输入密码"
                :value @passwordAtom
                :on-change #(reset! passwordAtom (.-value (.-target %)))
                }]
       [:i.mdi {:class (if @isShowPwd "mdi-eye-off" "mdi-eye")
                :style {:font-size 20 :align-self "center" :margin-left 4  :cursor "pointer"}
                :on-click #(reset! isShowPwd (not @isShowPwd))}]
       ]
      ))
  )

;;; ui
(defn editModel []
    (fn []
      (when @modal1
        [rc/modal-panel {:src (rc/at)
                         :backdrop-on-click #(reset! modal1 false)
                         :child [:div
                                 [:span (attr :font-size=32 :font-weight=600 ) "添加用户："]
                                 [ui/MyFormField {:label "姓名" :required true}
                                  [rc/input-text :src (at)
                                   :model (r/cursor dataItem [:username])
                                   :on-change #(swap! dataItem assoc :username %)
                                   :placeholder "请输入姓名"
                                   ]]
                                 [ui/MyFormField {:label "账号" :required true}
                                  [rc/input-text :src (at)
                                   :model (r/cursor dataItem [:code])
                                   :on-change #(swap! dataItem assoc :code %)
                                   :placeholder "请输入账号"
                                   ]]

                                 [ui/MyFormField {:label "性别" :required false}
                                  [rc/single-dropdown :src (at)
                                   :model (r/cursor dataItem [:sex])
                                   :on-change #(swap! dataItem assoc :sex %)
                                   :placeholder "请输入性别"
                                   :choices [{:id "男" :label "男"}
                                             {:id "女" :label "女"}
                                             ]
                                   ]
                                  ]

                                 [ui/MyFormField {:label "年龄" :required false}
                                  [rc/input-text :src (at)
                                   :model (str @(r/cursor dataItem [:age]))
                                   :on-change (fn [new-value]
                                                (if (re-matches #"\d*" new-value)
                                                  (swap! dataItem assoc :age (if (empty? new-value) nil (js/parseInt new-value)))))
                                   :placeholder "请输入年龄"
                                   ]
                                  ]
                                
                                 [ui/MyFormField {:label "密码" :required true}
                                  [pwdform ]
                                  ]
                                 [ui/MyFormField {:label "角色"}
                                  (log "get data for edit:" (:orgIds @dataItem) @dataItem)
                                  [rc/tree-select-dropdown {:src (at)
                                                            :choices @roleList
                                                            :id-fn #(:id %)
                                                            :label-fn #(:name %)
                                                            :model (r/cursor dataItem [:roleIds])
                                                            :on-change #(swap! dataItem assoc :roleIds %)
                                                            :width "250px"
                                                            }]]
                                 [ui/MyFormField {:label "组织"}
                                  [rc/tree-select-dropdown {:src (at)
                                                            :choices @orgList
                                                            :id-fn #(:id %)
                                                            :label-fn #(:name %)
                                                            :model (r/cursor dataItem [:orgIds])
                                                            :on-change #(swap! dataItem assoc :orgIds %)
                                                            :show-only-button? true
                                                            :show-reset-button? true
                                                            :width "250px"
                                                            }]]
                                 [ui/MyFormField {:label "说明"}
                                  [rc/input-textarea :src (at)
                                   :model (r/cursor dataItem [:description])
                                   :on-change #(swap! dataItem assoc :description %)
                                   ]]
                                 
                                 [:div (attr :flex :jc-e :gap=15)
                                  [:button.btn {:on-click #(reset! modal1 false)} "取消"]
                                  [:button.btn.btn-primary {:on-click #(saveItem @dataItem)} "确定"]
                                  ]
                                 ]}])))

;; Top tool bar

(defn handleUpload [event]
  (log "handle upload " event)
  (let [data (js->clj event)
        status (get-in data ["file" "status"])
        name (get-in data ["file" "name"])
        ]
    (log data)
    (if (= status "done")
      (showNotify "上传完成")
      (log "file update done")
      )
    )
  )

(defn searchForm []
  (let [searchParam (r/atom {})]
    (fn []
      [:div (attr :flex :jc-e :gap=5 )
       [ui/my-label "姓名："]
       [ui/MyInput {:model (r/cursor searchParam [:username])}]
       [ui/my-label "账号："]
       [ui/MyInput {:model (r/cursor searchParam [:code])}]
       
       [:button.btn.btn-primary (attr {:on-click #(loadData @searchParam)})
        [:i.fa.fa-search]
        "查询"]
       [:button.btn.btn-primary (attr {:on-click #(do (reset! searchParam {})
                                                      (loadData)
                                                      )})
        [:i.fa.fa-rotate-right]
        "重置"]
       ]
      )
    )
  )

(def selected-file (r/atom nil))

;; 上传文件
(defn upload-file [file]
  (let [form-data (js/FormData.)]
    (.append form-data "file" file)
    (POST "http://localhost:9010/ura/user/import?type=test&user=admin"
          {:body form-data
           :response-format :json
           :keywords? true
           :handler (fn [resp] (log resp))
           :error-handler (fn [er] (log er))})
    ))

;; 处理文件选择
(defn handle-file-select [event]
  (let [file (-> event .-target .-files (aget 0))]
    (reset! selected-file file)
    (println "Selected file:" (.-name file))
    (upload-file file)
    ))

;; 文件上传组件
(defn file-upload []
  [:div
   [:input {:type "file"
            :id "file-input"
            :style {:display "none"}
            :on-change handle-file-select}]
   [:button.btn.btn-primary {:on-click #(.click (js/document.getElementById "file-input"))}
    [:i.fa.fa-sign-in (attr :mr=5)] "用户导入"]
   ;; [:div
   ;;  (when @selected-file
   ;;    [:p "Selected file: " (.-name @selected-file)])]
   ])

(defn topBar []
  [ui/my-toolbar {}
   [:div (attr :flex :gap=5)
    [file-upload]
    
    [:a.btn.btn-primary {:href (getUrl "/ura/export/user")}
     [:span [:i.fa.fa-sign-out (attr :mr=5)] "用户导出"]
     ]

    [:button (attr :.btn :.btn-primary
                   {
                    :on-click #(
                                (reset! dataItem {:roleIds #{} :orgIds #{}})
                                (reset! modal1 true)
                                )
                    }) "添加用户"]
    ]
   [searchForm]
   ]
  )

(defn handleSelect [keys rows]
  (log "select row: " keys rows)
  (let [selected (js->clj rows :keywordize-keys true)]
    (showNotify (str "You have selected: " (map :username selected)))
    )
  )

(defn datatable []
  [:> ant/Table
   {:dataSource @(r/cursor tableData [:data])
    :striped "true"
    :row-key "id"
    :size "small"
    :columns [
              {:title "编号" :width 100 :dataIndex "id"}
              {:title "姓名" :width 100 :dataIndex "username"}
              {:title "账号" :width 100 :dataIndex "code"}
              ;; {:title "密码" :width 100 :dataIndex :password}
              {:title "性别" :width 100 :dataIndex "sex"}
              {:title "年龄" :width 100 :dataIndex "age"}
              ;; {:title "职级" :width 100 :dataIndex [:infos :position]}
              ;; {:title "单位" :width 100 :dataIndex [:infos :unit] }
              {:title "组织" :width 150 :dataIndex :orgInfoList
               :render (fn [r v]
                         (r/as-element
                          (->> (js->clj r {:keywordize-keys true})
                               (map :name)
                               (reduce #(str %1 "," %2))
                             )
                          )
                         )
               }
              {:title "角色" :width 150 :dataIndex :roleInfoList
               :render (fn [r v]
                         (r/as-element
                          (->> (js->clj r {:keywordize-keys true})
                              (map #(get % :name))
                              (reduce #(str %1 ", " %2))
                              )))}
              {:title "说明" :width 160 :dataIndex "description"}
              {:title "操作" :width 180 :fixed "right"
               :render (fn [row]
                         (let [value (js->clj row {:keywordize-keys true})]
                           (r/as-element
                            [:div (attr :flex :gap=5)
                             [:> ant/Popconfirm {:title "是否删除数据？"
                                                 :description (:name value)
                                                 :onConfirm #(callDelete value)
                                                 :okText "删除"
                                                 :cancelText "不删除"
                                                 }
                              [:> ant/Button {:size "small" :danger true} "删除"]]
                             
                             [:> ant/Button {:size "small" :on-click #(handleEdit value) } "编辑"]
                             ])
                           ))
               }
              ]
    
    :pagination {:show-size-changer true
                 :onShowSizeChange (fn [current pagesize]
                                     (swap! tableData assoc-in [:page :page-size] pagesize)
                                     (loadData)
                                     )
                 :onChange (fn [pagenumber]
                             (swap! tableData assoc-in [:page :current] pagenumber)
                             (loadData)
                             )
                 :page-size-options ["5" "10" "15" "30" "50" "100"]
                 :show-total #(str "总计 " % " 数据")
                 :current (:current (:page @tableData))
                 :page-size (:page-size (:page @tableData))
                 :total (:total (:page @tableData))
                 
                 }

   }])

(defn genPage []
  (loadData)
  (loadRoleList)
  (loadOrgList)
  (let []
    (fn []
      [:div
       ;;[:div {} (str (:page @tableData))]
       [editModel]
       [topBar]
       [datatable]
       ]
      ))
  )
